package com.zhendong.gulimall.order.listener;

import com.zhendong.gulimall.order.entity.OrderEntity;
import com.zhendong.gulimall.order.service.OrderService;
import com.zhendong.gulimall.order.utils.AlipayTemplate;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;

/**
 * TODO zhen @RabbitListener这个注解加在类上，然后让另一个注解@RabbitHandler加在方法上可以监听多个queue的消息.相当于方法重载一样OrderEntity entity这个实体类不同就有不同的方法来处理queue中的消息
 *
 * @author 孟享广
 * @date 2021-02-14 10:42 上午
 * @description
 */
@Service
@RabbitListener(queues = "order.release.order.queue")
public class OrderCloseListener {

    @Autowired
    AlipayTemplate alipayTemplate;

    @Autowired
    OrderService orderService;

    /**
     * TODO zhen 自己知道queue中的对象不一样，OrderEntity就换成其他对象再另写个方法接收就行实体类都是会被MQ自己转过来，Message是通用的可以获取header和body
     * gulimall-order这个系统和MQ只会建立一条TCP链接，具体的传输对象是通过当前的Channel来完成的
     */
    @RabbitHandler
    public void listening(OrderEntity entity, Channel channel, Message message) throws IOException {

        System.out.println("收到过期的订单，准备关闭订单。orderID:" + entity.getId() + "; orderSn:" + entity.getOrderSn());
        try {
            orderService.closeOrder(entity);
            //手动调用支付宝收单 p310 暂时不用手动 TODO zhen这是在收单自动超时时间到达的那一刻，支付成功了而这时候刚好订单关闭，说明订单关闭在支付之前执行了，所以就订单关闭后马上再手动调接口收单一下就好
            //TODO zhen deliveryTag是当前通道channel中按顺序自增的，这个不是消息的id，只是消息的一个标签
            long deliveryTag = message.getMessageProperties().getDeliveryTag();
            channel.basicAck(deliveryTag, false);
        } catch (IOException e) {
            //true 重新回到消息队列   TODO zhen 这情况一般也就网络的问题了
            channel.basicReject(message.getMessageProperties().getDeliveryTag(), true);

            //TODO zhen这个方法相当于是告诉MQ没有ack，但区别于basicReject的是basicNack可以指定MQ把这个消息丢掉不用再放回队列，但一般不这样，否则也失去了消息中间件的意义
            //channel.basicNack();
        }
    }
}
